package com.funcourse.demo.business;

import com.funcourse.demo.model.CompeteRoom;
import com.funcourse.demo.model.CompeteRoom.RoomStatus;
import com.funcourse.demo.model.CompeteRoom.RoomType;
import com.funcourse.demo.model.repo.CompeteRoomRepo;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class RoomCacher {

  @Autowired
  RedisTemplate redisTemplate;
  @Autowired
  CompeteRoomRepo competeRoomRepo;
  public static final String ROOM_KEY_PREFIX = "funcourse.room.realtime.";
  public static final String ROOM_KEY_SHADOW_PREFIX = "funcourse.room.shadow.realtime.";

  public CompeteRoom getRoomById(String roomId) {
    final long methodStartTimeMillis = System.currentTimeMillis();
    BoundValueOperations roomOps = redisTemplate
        .boundValueOps(ROOM_KEY_PREFIX + roomId);
    BoundValueOperations roomShadowOps = redisTemplate
        .boundValueOps(ROOM_KEY_SHADOW_PREFIX + roomId);
    final Object roomObject = roomOps.get();
    log.debug("time1 is {}",System.currentTimeMillis() - methodStartTimeMillis);
    if (null == roomObject) {
      final Optional<CompeteRoom> byId = competeRoomRepo.findById(roomId);
      log.debug("time2 is {}",System.currentTimeMillis() - methodStartTimeMillis);
      if (!byId.isPresent()) {
        return null;
      }
      final CompeteRoom competeRoom = byId.get();
      if (isRoomHot(competeRoom)) {
        roomOps.set(competeRoom,12, TimeUnit.HOURS);
        roomShadowOps.set("",12*60 -5, TimeUnit.MINUTES);
        log.debug("time3 is {}",System.currentTimeMillis() - methodStartTimeMillis);
      }
      return competeRoom;
    }
    return (CompeteRoom) roomObject;
  }

  private CompeteRoom persist(CompeteRoom competeRoom){
    competeRoomRepo.save(competeRoom);
    return competeRoom;
  }
  public void clear(String roomId){
    redisTemplate.delete(ROOM_KEY_PREFIX + roomId);
  }

  public CompeteRoom persist(String roomId,Boolean close){
    BoundValueOperations roomOps = redisTemplate
        .boundValueOps(ROOM_KEY_PREFIX + roomId);
    final Object roomObject = roomOps.get();
    if (null != roomObject) {
      final CompeteRoom competeRoom = (CompeteRoom) roomObject;
      if(close){
        competeRoom.setRoomStatus(RoomStatus.CLOSED);
        redisTemplate.delete(ROOM_KEY_PREFIX + roomId);
      }
      competeRoomRepo.save(competeRoom);
      return competeRoom;
    }
    return null;
  }

  /**
   * REAL_TIME / COLLECT
   * @param competeRoom
   */
  public void save(CompeteRoom competeRoom) {
    if(isRoomHot(competeRoom)){
      BoundValueOperations roomOps = redisTemplate
          .boundValueOps(ROOM_KEY_PREFIX + competeRoom.getId());
      roomOps.set(competeRoom);
    }else{
      persist(competeRoom);
    }

  }

  private boolean isRoomHot(CompeteRoom competeRoom) {
    return competeRoom.getRoomType() == RoomType.REAL_TIME
        && competeRoom.getRoomStatus() != RoomStatus.CLOSED;
  }

}
